/*
 * Copyright (C) 2016 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { ProtocolException } from "../Error/error"
import { Chain, Interceptor } from "../Interceptor"
import { Response, ResponseBuilder } from "../Response"
import { EMPTY_RESPONSE } from "../utils/Utils"
import { HttpMethod } from "./HttpMethod"
import { RealInterceptorChain } from "./RealInterceptorChain"


/** This is the last interceptor in the chain. It makes a network call to the server. */
export class CallServerInterceptor implements Interceptor {
  private forWebSocket: boolean
  constructor(forWebSocket: boolean) {
    this.forWebSocket = forWebSocket
  }

  // @Throws(IOException::class)
  async intercept(chain: Chain): Promise<Response> {
    let realChain = chain as RealInterceptorChain
    let exchange = realChain.exchange()
    let request = realChain.request()
    let requestBody = request.body
    let sentRequestMillis = Date.now()  // let sentRequestMillis = System.currentTimeMillis()
    exchange.writeRequestHeaders(request)
    let invokeStartEvent = true
    let responseBuilder: ResponseBuilder | null = null
    if (HttpMethod.permitsRequestBody(request.method) && requestBody !== null && requestBody !== undefined) {
      // If there's a "Expect: 100-continue" header on the request, wait for a "HTTP/1.1 100
      // Continue" response before transmitting the request body. If we don't get that, return
      // what we did get (such as a 4xx response) without ever transmitting the request body.
      if (request.header("Expect")?.toLowerCase() === "100-continue"){
        exchange.flushRequest()
        responseBuilder = await exchange.readResponseHeaders(true)
        exchange.responseHeadersStart()
        invokeStartEvent = false
      }

      if (responseBuilder === null || responseBuilder === undefined) {
        if (requestBody.isDuplex()) {
          // 不支持双向,暂不支持http2
          // Prepare a duplex body so that the application can send a request body later.
          // exchange.flushRequest()
          // let bufferedRequestBody = exchange.createRequestBody(request, true).buffer()
          // requestBody.writeTo(bufferedRequestBody)
        } else {
          // Write the request body if the "Expect: 100-continue" expectation was met.
          let bufferedRequestBody = await exchange.createRequestBody(request, false)
          await requestBody.writeTo(bufferedRequestBody)
          await bufferedRequestBody.close()
        }
      } else {
        exchange.noRequestBody()
        if (!exchange.connection.isMultiplexed) {
          // If the "Expect: 100-continue" expectation wasn't met, prevent the HTTP/1 connection
          // from being reused. Otherwise we're still obligated to transmit the request body to
          // leave the connection in a consistent state.
          exchange.noNewExchangesOnConnection()
        }
      }
    } else {
      exchange.noRequestBody()
    }

    if (requestBody === null || requestBody === undefined || !requestBody.isDuplex()) {
      await exchange.finishRequest()
      console.log("okhttp test log :: " , "timeout::请求体发送完毕 : ", Date.now().toString())
    }
    if (responseBuilder === null || responseBuilder === undefined) {
      responseBuilder = await exchange.readResponseHeaders(false)
      if (invokeStartEvent) {
        exchange.responseHeadersStart()
        invokeStartEvent = false
      }
    }
    console.log("okhttp test log :: " , "timeout::读取响应头 : ", Date.now().toString())
    let response: Response = responseBuilder
      .request(request)
      .handshake(exchange.connection.handshake())
      .sentRequestAtMillis(sentRequestMillis)
      .receivedResponseAtMillis(Date.now())
      .build()
    console.log("okhttp test log :: " , "timeout::构造响应体 : ", Date.now().toString())
    let code = response.code
    if (code == 100) {
      // Server sent a 100-continue even though we did not request one. Try again to read the actual
      // response status.
      responseBuilder = await exchange.readResponseHeaders(false)!!
      if (invokeStartEvent) {
        exchange.responseHeadersStart()
      }
      response = responseBuilder
        .request(request)
        .handshake(exchange.connection.handshake())
        .sentRequestAtMillis(sentRequestMillis)
        .receivedResponseAtMillis(Date.now())
        .build()
      code = response.code
    }

    exchange.responseHeadersEnd(response)

    if (this.forWebSocket && code === 101){
      response = response.newBuilder()
        .body(EMPTY_RESPONSE)
        .build()
    }else{
      console.log("okhttp test log :: " , "timeout::未解析响应体 : ", Date.now().toString())
      response = response.newBuilder()
        .body(exchange.openResponseBody(response))
        .build()
      console.log("okhttp test log :: " , "timeout::解析完响应体 : ", Date.now().toString())
    }
    if (response.request.header("Connection")?.toLowerCase() === "close" ||
      response.header("Connection")?.toLowerCase() === "close"){
      exchange.noNewExchangesOnConnection()
    }
    if ((code == 204 || code == 205) ){//&& response.body?.contentLength() ?: -1L > 0L) {
      throw new ProtocolException(`HTTP ${code} had non-zero Content-Length: ${response.body?.contentLength()}`)
    }
    console.log("okhttp test log :: " , "CallServerInterceptor : 全部结束")
    console.log("okhttp test log :: " , "ConnectInterceptor : 下半段结束")

    console.log("okhttp test log :: " , "timeout::解析完成 : ", Date.now().toString())
    return response
  }
}
